package hh.util;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import hh.util.jdbc.JdbcUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * sshIp      中转机器的ip
 * sshPort    中转机器的port
 * sshUser    中转机器的username
 * pwd        中转机器的password
 * localPort  本地port
 * targetIp   最终目标机器ip
 * targetPort 最终目标机器ip
 * <blockquote><pre>
 *     new SSH("root", "uCaUm6YOjh9OFyRl")
 *          .setSSHIpPort("10.201.2.2", 22)
 *          .setTargetIpPort("10.201.2.105", 3306)
 *          .setLocalPort(9090)
 *          .connect();
 * </pre></blockquote>
 * <p>
 * 现在访问 jdbc:mysql://localhost:9090  就可以 访问10.201.2.105：3306了
 *
 *
 * <p>
 */
@Slf4j
public class SSH {

    int localPort;

    String sshIp;
    int sshPort;
    String sshUser;
    String sshPassword;

    String targetIp;
    int targetPort;

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> closeAll()));
    }

    Session session;

    public static void main(String[] args) {
        new SSH("root", "uCaUm6YOjh9OFyRl")
                .setLocalPort(9090)
                .setSSHIpPort("10.201.2.2", 22)
                .setTargetIpPort("10.201.2.105", 3306)
                .connect();
    }

    public SSH() {
    }

    public SSH(String sshUser, String sshPassword) {
        this.sshUser = sshUser;
        this.sshPassword = sshPassword;
    }

    public static SSH getSession(String ip) {
        for (SSH ssh : sessions) {
            if (ssh.sshIp.equals(ip)) {
                return ssh;
            }
        }
        return null;
    }

    public SSH setSSHIpPort(String sshIp, int sshPort) {
        this.sshIp = sshIp;
        this.sshPort = sshPort;
        return this;
    }

    public SSH setTargetIpPort(String targetIp, int targetPort) {
        this.targetIp = targetIp;
        this.targetPort = targetPort;
        return this;
    }

    public SSH setLocalPort(int localPort) {
        this.localPort = localPort;
        return this;
    }


    public static void closeAll() {
        sessions.forEach(e -> e.getSession().disconnect());
    }

    private static List<SSH> sessions = new ArrayList<>();

    /**
     * 举例：openSSH("188.12.12.1","root","root",9527,"172.8.22.1",3306)
     * <p>
     * 代表的意思是，
     * 当我访问localhost:9527的时候
     * 他会用ssh登录 188.12.12.1:22
     * 然后将请求转发到目标机器 172.8.22.1:3306
     * </p>
     */
    @SneakyThrows
    public void connect() {
        JSch jSch = new JSch();
        session = jSch.getSession(sshUser, sshIp, sshPort);
        session.setPassword(sshPassword);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
        session.setPortForwardingL(localPort, targetIp, targetPort);
        log.info(getSSHInfo(session));
        sessions.add(this);
    }

    public Session getSession() {
        return session;
    }

    private static String getSSHInfo(Session e) throws JSchException {
        String[] s = e.getPortForwardingL()[0].split(":");
        return String.format("ssh打开成功  请访问-->localhost:%s  ssh到-->%s:%s  转发到-->%s:%s  version: %s",
                s[0], e.getHost(), e.getPort(), s[1], s[2], e.getServerVersion());
    }
}
